home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 406_01 / disked25 / source / setup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  20.1 KB  |  791 lines

  1. /***
  2. *setup.c - disk editor setup
  3. *
  4. *Copyright (c) 1991-1994, Gregg Jennings.  All wrongs reserved.
  5. *   P O Box 200, Falmouth, MA 02541-0200
  6. *
  7. *Purpose:
  8. *   Initialization.
  9. *
  10. *Notice:
  11. *   This progam may be freely used and distributed.  Any distrubution
  12. *   with modifications must retain the above copyright statement and
  13. *   modifications noted.
  14. *   No pulp-publication, in whole or in part, permitted without
  15. *   permission (magazines or books).
  16. *******************************************************************************/
  17.  
  18. /*
  19.    Versions:
  20.  
  21.    2.1 04-Jan-1994   added get_volume()
  22. */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <dos.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #include <malloc.h>
  30. #include <fcntl.h>
  31. #include <io.h>
  32. #include <direct.h>
  33. #include <errno.h>
  34.  
  35. #include "disked.h"
  36. #include "diskio.h"
  37. #include "files.h"
  38. #include "mylib.h"
  39. #include "alloc.h"
  40. #include "error.h"
  41. #include "direct.h"
  42.  
  43. const char *Author="Gregg Jennings";
  44. const char *Title="DISKED The DISK EDitor";
  45. const char *Copyr="(c) 1989-1994, All wrongs reserved";
  46. const char *Namep="DISKED";
  47.  
  48. #ifdef _QC
  49. const char *Version=" 2.5.A.1293";
  50. #elif __BORLANDC__
  51. const char *Version=" 2.5.B.1293";
  52. #else
  53. const char *Version=" 2.5.C.1293";
  54. #endif
  55.  
  56. char *disked_ini="DISKED.INI";
  57. char *disked_sav="DISKED.SAV";
  58.  
  59. extern char curdir[67];                /* current directory each drive */
  60. extern char comspec[FILENAME_MAX];     /* for shell command */
  61. extern char inifile[67];               /* initialization file name */
  62. extern char savfile[67];               /* save place file name */
  63. extern int Save,Restore;               /* more switches */
  64. extern int files_indexed;              /* files-indexed flag */
  65. extern int find_flag;                  /* find string arg */
  66. #ifdef SET_TO_DIR
  67. extern int dir_flag;                   /* set-to dir arg */
  68. extern char dir_str[67];
  69. #endif
  70. extern char tmpfstr[];                 /* find string, entry */
  71. extern char findstr[];                 /* find string, actual */
  72. extern unsigned int findlen;           /* find string, length */
  73. extern int min_mem;                    /* minimize menory allocation */
  74. extern int write_to;                   /* double protection on write */
  75.  
  76. extern unsigned long tagged[10];       /* "tagged" sectors */
  77.  
  78. extern unsigned int byte_cnt;          /* buffer byte count */
  79. extern unsigned int max_bytes;         /* maximum buffer size */
  80. extern int Signon;                     /* signon message */
  81. extern unsigned char *save_sec;        /* duplicate sector buffer */
  82. extern unsigned char *spare_sec;       /* spare sector buffer */
  83.  
  84. void _cdecl _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr);
  85.  
  86. /*
  87.  *   SETUP  new drive, valid drive array, drive to use
  88.  *
  89.  *   ver 2.4   03-Dec-1993    added /@
  90.  *   ver 2.3   20-Nov-1993    order of options parsed
  91.  *   ver 2.2   13-Nov-1993    better finding of INI file, newalloc()
  92.  *   ver 2.1   19-Apr-1992    Added /?
  93.  */
  94.  
  95. int setup(char **argv, int drives[], unsigned int *dsk)
  96. {
  97. int c;
  98. unsigned i,tempd,cdisk;
  99. char tmpstr[MAXSTR+1];
  100. char prompt_env[FILENAME_MAX];
  101. char *tempc;
  102.  
  103.    write_to = FALSE;
  104.    byte_cnt = 0;
  105.    files_indexed = FALSE;
  106.    Signon = TRUE;
  107.    Save = Restore = FALSE;
  108.    find_flag = min_mem = 0;
  109.    n_files = 1;
  110.    n_dirs = 1;
  111.  
  112.    /* get drive info */
  113.  
  114.    max_drive=0;
  115.    _dos_getdrive(&cdisk);                    /* get current drive */
  116.    *dsk=cdisk;                               /* copy it */
  117.    for (i=0;i<MAX_DRIVE;i++)                 /* loop to verify drive # */
  118.    {
  119.        _dos_setdrive(i,&tempd);              /* try and set */
  120.        _dos_getdrive(&tempd);                /* see if it was set */
  121.        if (i==tempd)
  122.        {
  123.            drives[i]=TRUE;
  124.            ++max_drive;
  125.        }
  126.        else
  127.            drives[i]=FALSE;
  128.    }
  129.  
  130.    _dos_setdrive(cdisk,&tempd);              /* reset current disk */
  131.  
  132.    strcpy(comspec,getenv("COMSPEC"));        /* get where COMMAND.COM is */
  133.    strcpy(prompt_env,getenv("PROMPT"));      /* change prompt for shell */
  134.    strcpy(tmpstr,"PROMPT=");
  135.    strcat(tmpstr,prompt_env);
  136.    strcat(tmpstr,"(DE)");
  137.    putenv(tmpstr);
  138.  
  139.    tempd = 1;                                /* for INI file test */
  140.  
  141.    if ((tempc=getenv("INIT"))!=NULL)
  142.    {
  143.       strcpy(savfile,tempc);                 /* get env dir */
  144.       strcpy(inifile,tempc);
  145.       if (inifile[strlen(inifile)-1]!='\\')
  146.       {
  147.          strcat(savfile,"\\");
  148.          strcat(inifile,"\\");
  149.       }
  150.       strcat(savfile,disked_sav);
  151.       strcat(inifile,disked_ini);
  152.       tempd = !exist(inifile);
  153.    }
  154.    if (tempd)                               /* if INI file not in dir */
  155.    {
  156.       strcpy(savfile,*argv);                /* get where DISKED resides */
  157.       strcpy(inifile,*argv);
  158.       i=strlen(inifile);
  159.       inifile[--i]='I';
  160.       inifile[--i]='N';
  161.       inifile[--i]='I';
  162.       i=strlen(savfile);
  163.       savfile[--i]='V';
  164.       savfile[--i]='A';
  165.       savfile[--i]='S';
  166.    }
  167.  
  168.    /* initialize */
  169.  
  170.    init(inifile);
  171.  
  172.    /* capture INT 24 handler */
  173.  
  174.    _harderr(hhandler);
  175.  
  176.    /* check command line parameters */
  177.  
  178.    if (*++argv)
  179.    {
  180.       do
  181.       {
  182.          c=tolower(**argv);
  183.          if (c == '-')                 /* turn things off */
  184.          {
  185.             switch (*++*argv)
  186.             {
  187.                case 's': Save=FALSE;    break;
  188.                case 'r': Restore=FALSE; break;
  189.                case 'f': Files=FALSE;   break;
  190.                case 'h': Home=FALSE;    break;
  191.                default:  continue; break;
  192.             }
  193.          }
  194.          else if (c == '/')            /* do/set things */
  195.          {
  196.             switch (*++*argv)
  197.             {
  198.                case 'h':               /* help ! */
  199.                case '?':
  200.                   command_line();
  201.                   exit(0);
  202.                   break;
  203.                case 'x':               /* set INI file name */
  204.                   ++*argv;
  205.                   if (*argv)
  206.                      strcpy(inifile,*argv);
  207.                   break;
  208.                case 's':               /* set SAV file name */
  209.                   ++*argv;
  210.                   if (*argv)
  211.                      strcpy(savfile,*argv);
  212.                   break;
  213.                case 'm':               /* minimize memory */
  214.                   min_mem = 1;
  215.                   break;
  216.                case 'f':               /* find string arg */
  217.                   ++*argv;
  218.                   if (*argv[0])        /* be careful of space after 'f' */
  219.                   {
  220.                      find_flag = 1;
  221.                      strcpy(findstr,*argv);
  222.                   }
  223.                   else
  224.                   {
  225.                      if (*++argv)
  226.                      {
  227.                         find_flag = 1;
  228.                         strcpy(findstr,*argv);
  229.                      }
  230.                      else
  231.                         *--argv; /* fool the do while loop */
  232.                   }
  233.                   break;
  234.                case '@':
  235.                   Signon = 0;
  236.                   break;
  237.                default:
  238.                   continue;
  239.                   break;
  240.             }
  241.          }
  242.          else if (c == '+')            /* turn things on */
  243.          {
  244.             switch (*++*argv)
  245.             {
  246.                case 's': Save=TRUE; break;
  247.                case 'r': Restore=TRUE; break;
  248.                case 'f':
  249.                   if (find_flag == 1)
  250.                      find_flag = 2;          /* index files AFTER find() */
  251.                   Files = TRUE;
  252.                   break;
  253.                case 'h': Home=TRUE; break;
  254.                default: continue; break;
  255.             }
  256.          }
  257.          else if (isalpha(c))                /* disk drive letter */
  258.          {
  259.              tempd=toupper(**argv)-'@';      /* make valid */
  260.              if (drives[tempd])              /* check it */
  261.              {
  262.                  *dsk=tempd;                 /* log it */
  263.                  Restore=FALSE;              /* drive spec higher precedence */
  264.                  /*Save=FALSE;*/             /*  than Restore */
  265.              }
  266.          }
  267.       } while (*++argv);
  268.    }
  269.    return(cdisk);
  270. }
  271.  
  272. /* define NON-DOS formats */
  273. /*#define DISKTYPE                 /* not implemented yet */
  274.  
  275. void command_line(void)
  276. {
  277. print("\n\t");print(Copyr);print(Version);
  278. #ifdef DISKTYPE
  279. print("\n\tDISKED [-|+srfh] [/x{inifile}] [/s{savefile}] [/f{text}] [/m] [d:] [/td:nnn]\n\n");
  280. #else
  281. print("\n\tDISKED [-|+srfh] [/x{inifile}] [/s{savefile}] [/f{text}] [/m] [d:]\n\n");
  282. #endif
  283. print("\toptions: - off  + on\n");
  284. print("\t         s save\n");
  285. print("\t         r restore\n");
  286. print("\t         f files\n");
  287. print("\t         h home\n\n");
  288. print("\t         {inifile} initialization file override\n");
  289. print("\t         {savefile} save file override\n");
  290. print("\t         {text} find text\n");
  291. print("\t         m minimize file buffer size\n");
  292. print("\t         d: drive\n");
  293. #ifdef DISKTYPE
  294. print("\t         t:nnn disk type:\n");
  295. #endif
  296. }
  297.  
  298. void signon_msg(void)
  299. {
  300. send('\n');
  301. printc(Title);
  302. printc(Copyr);
  303. printc("This is Freeware.");
  304. printc(__DATE__);
  305. print("\n\t     This program is still being improved and feedback from");
  306. print("\n\tusers is extremely essential!\n");
  307. print("\n\t     Anyone sending me their name and address is entitled for");
  308. print("\n\ta postscript printed manual, free future versions and support.\n");
  309. print("\n\t     NOTE: It is okay to give this program away.\n");
  310. print("\n\t     ALSO: Please read the documentation that should come with");
  311. print("\n\tthis program for important copyleft information.  If the");
  312. print("\n\tdocumentation is missing, please write me for a copy.\n");
  313. print("\n\t     AND: This version LETS YOU WRITE to the disk.  NO WARRANTY");
  314. print("\n\tis made, expressed, or implied.\n");
  315. print("\n\t     THANK YOU      Gregg Jennings");
  316. print("\n\t                    P O Box 200");
  317. print("\n\t                    Falmouth  MA  02540-0200\n");
  318. }
  319.  
  320. /*
  321.    Read DISKED.INI and set the world.
  322.  
  323.    ver   2.0   removed "boot" and "video" 02-Dec-1993
  324.    ver   1.1   added "Expert"
  325. */
  326.  
  327. void init(char *filename)
  328. {
  329. char string[100], *seps = " \t\n,:=";
  330. register char *p;
  331. FILE *file;
  332.  
  333.    if (stricmp(filename,"none")==0 || filename[0]=='\0')
  334.       return;
  335.  
  336.    if ((file=fopen(filename,"r"))==NULL)
  337.    {
  338.       if (errno==ENOENT) {
  339.          errno=0;
  340.          file=fopen(disked_ini,"r");
  341.       }
  342.       if (errno!=0)
  343.       {
  344.          if (errno!=ENOENT)
  345.             perror(filename);
  346.          return;
  347.       }
  348.    }
  349.  
  350.    while (!feof(file))
  351.    {
  352.       if (fgets(string,100,file) == NULL)
  353.          break;
  354.  
  355.       if ((p = strtok(string,seps)) == NULL)
  356.          continue;
  357.  
  358.       if (*p == ';' || *p == '/')
  359.          continue;
  360.  
  361.       if (stricmp("radix",p) == 0)
  362.       {
  363.          p = strtok(NULL,seps);
  364.          if (p)
  365.             if ((Radix = numarg(p,Radix)) < 1 || Radix >26)
  366.                Radix = 10;
  367.          continue;
  368.       }
  369.       else if (stricmp("ascii",p) == 0)
  370.       {
  371.          p = strtok(NULL,seps);
  372.          if (p) Ascii = boolarg(p);
  373.          continue;
  374.       }
  375.       else if (stricmp("convert",p)==0)
  376.       {
  377.          p = strtok(NULL,seps);
  378.          if (p) Convert = boolarg(p);
  379.          continue;
  380.       }
  381.       else if (stricmp("display",p)==0)
  382.       {
  383.          p = strtok(NULL,seps);
  384.          if (p) Display = boolarg(p);
  385.          continue;
  386.       }
  387.       else if (stricmp("files",p)==0)
  388.       {
  389.          p = strtok(NULL,seps);
  390.          if (p) Files = boolarg(p);
  391.          continue;
  392.       }
  393.       else if (stricmp("get",p)==0)
  394.       {
  395.          p = strtok(NULL,seps);
  396.          if (p) Get = boolarg(p);
  397.          continue;
  398.       }
  399.       else if (stricmp("home",p)==0)
  400.       {
  401.          p = strtok(NULL,seps);
  402.          if (p) Home = boolarg(p);
  403.          continue;
  404.       }
  405.       else if (stricmp("verify",p)==0)
  406.       {
  407.          p = strtok(NULL,seps);
  408.          if (p) Verify = boolarg(p);
  409.          continue;
  410.       }
  411.       else if (stricmp("partial",p)==0)
  412.       {
  413.          p = strtok(NULL,seps);
  414.          if (p) Partial = boolarg(p);
  415.          continue;
  416.       }
  417.       else if (stricmp("mask",p)==0)
  418.       {
  419.          p = strtok(NULL,seps);
  420.          if (p) Mask = boolarg(p);
  421.          continue;
  422.       }
  423.       else if (stricmp("strip",p)==0)
  424.       {
  425.          p = strtok(NULL,seps);
  426.          if (p) Strip = boolarg(p);
  427.          continue;
  428.       }
  429.       else if (stricmp("write",p)==0)
  430.       {
  431.          p = strtok(NULL,seps);
  432.          if (p) write_to = boolarg(p);
  433.          continue;
  434.       }
  435.       else if (strcmp("Expert",p)==0)
  436.       {
  437.          write_to = Write = Files = Translate = 1;
  438.          Display = Verify = Home = Strip = Signon = 0;
  439.          continue;
  440.       }
  441.       else if (stricmp("signon",p)==0)
  442.       {
  443.          p = strtok(NULL,seps);
  444.          if (p) Signon = boolarg(p);
  445.          continue;
  446.       }
  447.       else if (stricmp("debug",p)==0)
  448.       {
  449.          p = strtok(NULL,seps);
  450.          if (p) Debug = boolarg(p);
  451.          continue;
  452.       }
  453.       else if (stricmp("save",p)==0)
  454.       {
  455.          p = strtok(NULL,seps);
  456.          if (p) Save = boolarg(p);
  457.          continue;
  458.       }
  459.       else if (stricmp("restore",p)==0)
  460.       {
  461.          p = strtok(NULL,seps);
  462.          if (p) Restore = boolarg(p);
  463.          continue;
  464.       }
  465.       else if (stricmp("translate",p)==0)
  466.       {
  467.          p = strtok(NULL,seps);
  468.          if (p) Translate = boolarg(p);
  469.          continue;
  470.       }
  471.    }
  472. }
  473.  
  474. /* save position, tagged sectors, find string */
  475.  
  476. /* to do:  save all switches */
  477.  
  478. void saveinit(char *filename)
  479. {
  480. FILE *file;
  481. int i;
  482.  
  483.    if ((file=fopen(filename,"w"))==NULL)
  484.    {
  485.       perror(filename);
  486.       return;
  487.    }
  488.    fputs("; DISKED.SAV\n",file);
  489.    fprintf(file,"disk %c:\n",disk+'A'-1);
  490.    fprintf(file,"sector %u\n",log_sector);
  491.    fputs("tagged ",file);
  492.    for (i=1;i<10;i++)
  493.       fprintf(file,"%ld ",tagged[i]);
  494.    fputs("\t;tagged sectors\n",file);
  495.    if (tmpfstr[0])
  496.       fprintf(file,"find %s\n",tmpfstr);
  497.    fclose(file);
  498. }
  499.  
  500. /* restore position, tagged sectors, find string */
  501.  
  502. /* to do:  restore all switches */
  503.  
  504. int getinit(char *filename)
  505. {
  506. char string[100], *seps = " \t\n,:=";
  507. register char *p;
  508. FILE *file;
  509.  
  510.    if ((file=fopen(filename,"r"))==NULL)
  511.    {
  512.       if (errno!=ENOENT)
  513.          perror(filename);
  514.       return(0);
  515.    }
  516.  
  517.    while (!feof(file))
  518.    {
  519.       if (fgets(string,100,file) == NULL)
  520.           break;
  521.  
  522.       if (((p = strtok(string,seps)) == NULL) || (*p == ';' || *p == '/'))
  523.           continue;
  524.  
  525.       if (stricmp("disk",p) == 0)
  526.       {
  527.          p = strtok(NULL,seps);
  528.          if (p) disk = keyarg(strupr(p),disk)-'A'+1;
  529.          continue;
  530.       }
  531.       if (stricmp("sector",p) == 0)
  532.       {
  533.          p = strtok(NULL,seps);
  534.          if (p) log_sector = (unsigned int)longarg(p,10);
  535.          continue;
  536.       }
  537.       if (stricmp("tagged",p) == 0)
  538.       { int i;
  539.          for (i=0;i<10;i++)
  540.          {
  541.             p = strtok(NULL,seps);
  542.             if (p) tagged[i] = numarg(p,10);
  543.          }
  544.          continue;
  545.       }
  546.       if (stricmp("find",p) == 0)
  547.       {
  548.          p = strtok(NULL,seps);
  549.          if (p)
  550.          {
  551.             strcpy(tmpfstr,p);
  552.             strcpy(findstr,p);
  553.             findlen=convert(findstr);              /* convert if needed */
  554.          }
  555.          continue;
  556.       }
  557.    }
  558.    fclose(file);
  559.    return(1);
  560. }
  561.  
  562. unsigned int numarg(char *arg, int radix)
  563. {
  564. unsigned int i=0;
  565.  
  566.    if (radix==10)
  567.       sscanf(arg,"%u",&i);
  568.    else
  569.       sscanf(arg,"%x",&i);
  570.    return(i);
  571. }
  572.  
  573. unsigned long longarg(char *arg,int radix)
  574. {
  575. unsigned long l=0L;
  576.  
  577.    if (radix==10)
  578.       sscanf(arg,"%lu",&l);
  579.    else
  580.       sscanf(arg,"%lx",&l);
  581.    return(l);
  582. }
  583.  
  584. /*
  585.    sets a boolean keyword: "on"           returns 1
  586.                            "off" or NULL  returns 0
  587. */
  588. int boolarg(char *arg)
  589. {
  590.    return (arg && (stricmp("on",arg)==0 || stricmp("yes",arg)==0));
  591. }
  592.  
  593. /* assigns a key value: "^a" - "^z"  returns to 01 - 1Ah
  594.                         ""           returns key
  595.                         "off"        returns -1
  596. */
  597.  
  598. int keyarg(char *arg,int key)
  599. {
  600. register int i;
  601.  
  602.    if (arg==NULL)
  603.       i=key;
  604.    else if (stricmp("off",arg)==0)
  605.       i=-1;
  606.    else if ((stricmp("^`",arg)+stricmp("^{",arg))==0)
  607.       i=*(++arg)-'`';
  608.    else
  609.       i=*arg;
  610.    return(i);
  611. }
  612.  
  613. /* view file to screen */
  614.  
  615. void viewfile(char *filename)
  616. {
  617. char buf[255];
  618. FILE *fh;
  619. int i=1;
  620.  
  621.    if (stricmp(filename,"none")==0 || filename[0]=='\0')
  622.       return;
  623.  
  624.    if ((fh=fopen(filename,"r"))==NULL)
  625.    {
  626.       perror(filename);
  627.       return;
  628.    }
  629.    if (Display)
  630.    {
  631.       conout(' ');
  632.       print(filename);
  633.       print(" File Contents:\n\n");
  634.    }
  635.    else
  636.       send('\n');
  637.    while (!feof(fh))
  638.    {
  639.       if (fgets(buf,255,fh)==NULL)
  640.          break;
  641.       printf(buf);
  642.       if (++i==23)
  643.       {
  644.          print("<more>\r");
  645.          i=input();
  646.          if (i==0)
  647.             input();
  648.          print("      \r");
  649.          if (i==ESC)
  650.             break;
  651.          else
  652.             i=0;
  653.       }
  654.    }
  655.    fclose(fh);
  656. }
  657.  
  658. /* command prompt */
  659.  
  660. int prompt(int n, int base)
  661. {
  662. unsigned int key;
  663.  
  664.     conout('(');
  665.     pnlz(n,(base==16)?4:5,base);
  666.     conout(')');
  667.     if (byte_cnt==max_bytes)
  668.       conouta(' ',15);
  669.     if (Files && n_files>1)
  670.       conout(15);
  671.     else
  672.       conout('*');
  673.     bdos(0x0c,0,0);
  674.     key=conin();
  675.     if ((key&0xff)==0 || key>0x3920 || key<0x011B)
  676.         return(key);
  677.     return(key&0xff);
  678. }
  679.  
  680. int do_files(void);
  681.  
  682. /* consolated disk change stuff */
  683.  
  684. int newdisk(int tempd)
  685. {
  686. int i;
  687. unsigned int temps;
  688.  
  689.    temps=sec_size;               /* save current sector size */
  690.    savesector();                 /* and sector data */
  691.    if ((i=logdisk(tempd)) != DISK_OK)
  692.    {
  693.       restoresector();
  694.       return(0);
  695.    }
  696.    if (temps!=sec_size)          /* new sector size */
  697.    {
  698.        sec_buf = newalloc(sec_buf,sec_size*sizeof(char));
  699.        if (sec_buf == NULL)
  700.        {
  701.            print("\nReallocation Failure.\n");
  702.            print("Sorry, but I am too confused to continue...\n");
  703.            exit(3);
  704.        }
  705.        save_sec  = newalloc(save_sec,sec_size*sizeof(char));
  706.        spare_sec = newalloc(spare_sec,sec_size*sizeof(char));
  707.    }
  708.    getcwd(curdir,66);            /* get current directory */
  709.    n_files = 1;                  /* setup for files */
  710.    n_dirs = 1;
  711.  
  712.    if (Files)                    /* if to index them */
  713.    {
  714.       if (files_indexed)         /* if already */
  715.       {
  716.          freep(clusters);        /* free them first */
  717.          freep(files);
  718.       }
  719.       do_files();
  720.    }
  721.    if (!Files)
  722.       get_volume(volume);
  723.  
  724.    memset(tagged,0,sizeof(tagged));
  725.  
  726.    if (Home)
  727.       rootsector();
  728.    else
  729.    {
  730.       /*
  731.       temps = (unsigned)cwdstart();
  732.       setsector(temps);
  733.       */
  734.       if (log_sector>=num_sectors)
  735.          lastsector();
  736.       else
  737.          readsector();
  738.    }
  739.    return(1);
  740. }
  741.  
  742. char *harderr_list[] = {
  743.    "Disk is write-protected",
  744.    "Unknown unit",
  745.    "Drive not ready",
  746.    "Unknown command",
  747.    "CRC error in data",
  748.    "Bad drive-request structure length",
  749.    "Seek error",
  750.    "Unknown media type",
  751.    "Sector not found",
  752.    "Printer out of paper",
  753.    "Write fault",
  754.    "Read fault",
  755.    "General failure",
  756. };
  757.  
  758. /* Handler to deal with hard error codes. Since DOS is not reentrant,
  759.  * it is not safe to use DOS calls for doing I/O within the DOS Critical
  760.  * Error Handler (int 24h) used by _harderr. Therefore, screen output and
  761.  * keyboard input must be done through the BIOS.
  762.  */
  763. void _cdecl _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr)
  764. {
  765.    if (doserr >= 0 && doserr <= 0x0C)
  766.       error.msg = harderr_list[doserr];
  767.    error.num = doserr;
  768.    error.mod = error.func = "harderr";
  769.    _hardretn(doserr&0xff);
  770. }
  771.  
  772. /* exit() shell */
  773.  
  774. void quit(int e)
  775. {
  776.    print(err_msg[e]);
  777.    exit(e);
  778. }
  779.  
  780. /* common index files stuff */
  781.  
  782. int do_files(void)
  783. {
  784.    if (Display)
  785.       bprint(" indexing...");
  786.    files_indexed = Files = initfiles();
  787.    if (Display)
  788.       clreol();
  789.    return files_indexed;
  790. }
  791.